#include"Thread.hpp"
#include"Blockqueue.hpp"
#include"Task.hpp"
#include<vector>
#include<unistd.h>
#include<cstdlib>
#include<ctime>

using namespace zzx;

void print() //functional包装器函数
{
    std::cout << "print log" << std::endl;
}

using blockqueue_t = BlockQueue<Task>; 

void Consumer(blockqueue_t& bq, string who)
{
    sleep(5);
    while(true)
    {
        //1.任务类型为类对象
        Task t;
        //a.从阻塞队列中读取任务(消费任务)
        bq.PopQueue(&t);
        //b.处理任务
        t.Excute();
        std::cout << who << " data: ";
        //t(); 2.任务类型为函数
        t.ResultToString();
        sleep(1);
    }
} 

void Producer(blockqueue_t& bq, string who) 
{
    srand(time(NULL));
    while(true)
    {
        //1.任务类型为类对象
        //a.获取任务
        int a = rand() % 20;
        int b = rand() % 15;
        Task t(a, b);
        //Task t = print; 2.任务类型为函数
        //b.向阻塞队列中放入任务(生产任务)
        bq.EnQueue(t); 
        std::cout << who << " data: ";
        t.DebugToString();
        sleep(1);
    }
}

void CommonCode(std::vector<thread<blockqueue_t>> *threads, int num, blockqueue_t& bq, fun_c<blockqueue_t&> fc, string s)
{
    for(int i = 0; i < num; i++)
    {
        char* name = new char(64);
        snprintf(name, 64, "%s-%d", s.c_str(), i + 1);
        
        thread<blockqueue_t> td(fc, bq, name);
        //td.start(); x + sleep(5); √
        threads->push_back(td);
        //threads->back().start(); x
    }
}

void StartConsumer(std::vector<thread<blockqueue_t>> *threads, int num, blockqueue_t& bq)
{
    CommonCode(threads, num, bq, Consumer, "comsumer");
}

void StartProducer(std::vector<thread<blockqueue_t>> *threads, int num, blockqueue_t& bq)
{
    CommonCode(threads, num, bq, Producer, "producer");
}

void StartAllThread(std::vector<thread<blockqueue_t>>& threads)
{
    for(auto& td : threads)
    {
        td.start();
    }
}

void WaitThreads(std::vector<thread<blockqueue_t>>& threads)
{
    for(auto& td : threads)
    {
        td.join();
    }
}

int main()
{
    vector<thread<blockqueue_t>> threads;
    blockqueue_t bq(5);
    StartProducer(&threads, 3, bq); 
    StartConsumer(&threads, 3, bq);
    StartAllThread(threads);
    WaitThreads(threads);

    return 0;
}